﻿using BLToolkit.Data.Linq;
using SettlersAuto.Data.AmfTypes;
using SettlersAuto.Data.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SettlersAuto.Data
{
    public class ServerResponseHandler
    {
        private SettlersAutoDb _db;

        public ServerResponseHandler(SettlersAutoDb db)
        {
            _db = db;
        }

        public void ProcessTradeWindowResult(int sessionId, TradeWindowResultVO tradeWindowResult)
        {
            foreach (var slot in tradeWindowResult.TradeOffers.Select(ParseTradeSlot))
            {
                slot.TradeSessionId = sessionId;
                _db.InsertOrReplace(slot);
            }
        }

        private static TradeSlot ParseTradeSlot(TradeObjectVO tradeObject)
        {
            var goodsParts = tradeObject.offer.Split('|');

            if (goodsParts.Length != 3)
            {
                return null;
            }

            var offer = ParseProduct(goodsParts[0]);
            var demand = ParseProduct(goodsParts[1]);

            return new TradeSlot
            {
                TradeSlotId = tradeObject.id,
                SenderId = tradeObject.senderID,
                SenderName = tradeObject.senderName,
                LotsCount = tradeObject.lotsRemaining,
                OfferProductName = offer.Name,
                OfferQuantity = Math.Max(offer.Quantity, 1),
                DemandProductName = demand.Name,
                DemandQuantity = Math.Max(demand.Quantity, 1)
            };

        }

        public int InsertTradeSession(byte[] bytes)
        {
            var session = new TradeSession
            {
                Timestamp = DateTime.UtcNow,
                RawData = bytes
            };
            var sessionId = (int)(decimal)_db.InsertWithIdentity(session);
            return sessionId;
        }

        private static SlotProduct ParseProduct(string productString)
        {
            var parts = productString.Split(',');

            var nameParts = parts.TakeWhile(s => !FirstIsDigit(s));
            var name = string.Join("", nameParts);

            var restPart = parts.SkipWhile(s => !FirstIsDigit(s));

            if (name.StartsWith("Adventure") || name.StartsWith("BuildBuilding"))
            {
                return new SlotProduct(name, 1);
            }
            if (name.StartsWith("FillDeposit"))
            {
                var quantity = int.Parse(restPart.FirstOrDefault());
                return new SlotProduct(name, quantity);
            }

            if (restPart.FirstOrDefault() == "1" && restPart.Skip(1).FirstOrDefault() == "1" && restPart.Skip(2).FirstOrDefault() == "0")
            {
                restPart = restPart.Skip(3).ToList();
            }

            if (restPart.Any())
            {
                try
                {
                    var quantity = int.Parse(string.Join("", restPart));
                    return new SlotProduct(name, quantity);
                }
                catch (Exception)
                {
                    System.Diagnostics.Debug.WriteLine("Failed to parse product string'" + productString + "'");
                }
            }

            return new SlotProduct(name, 1);
        }

        private static bool FirstIsDigit(string str)
        {
            return !string.IsNullOrEmpty(str) && Char.IsDigit(str[0]);
        }
    }
}
